package com.geekhalo.schedule.v3;

import com.geekhalo.schedule.task.TaskConfig;
import com.geekhalo.schedule.task.TaskService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

@Service
@Slf4j
public class LoadAndConfigScheduleService {
    private final Map<Long, TaskEntry> taskEntry = new HashMap<>();

    @Autowired
    private TaskService taskService;

    @Autowired
    private TaskScheduler taskScheduler;

    @Autowired
    private TaskDefinitionV3Repository repository;


    @Scheduled(fixedDelay = 1000, initialDelay = 1000)
    public void loadAndConfig(){
        // 加载所有的任务信息
        List<TaskDefinitionV3> tasks = repository.findAll();
        // 遍历任务进行任务检查
        for (TaskDefinitionV3 task : tasks){
            // 获取内存任务状态
            TaskEntry taskEntry = this.taskEntry.computeIfAbsent(task.getId(), TaskEntry::new);

            if (task.isEnable() && taskEntry.isStop()){
                // 任务为可用，运行状态为停止，则重新进行 schedule 注册
                ScheduledFuture<?> scheduledFuture = this.taskScheduler.scheduleWithFixedDelay(new TaskRunner(task), task.getDelay() * 1000);
                taskEntry.setScheduledFuture(scheduledFuture);
                log.info("success to start schedule task for {}", task);

            }else if (task.isDisable() && taskEntry.isRunning()){
                // 任务为禁用，运行状态为运行中，停止正在运行在任务
                taskEntry.stop();
                log.info("success to stop schedule task for {}", task);
            }
        }
    }

    @Data
    private class TaskEntry{
        private final Long taskId;
        private ScheduledFuture scheduledFuture;
        private TaskEntry(Long taskId) {
            this.taskId = taskId;
        }

        /**
         * 内存状态 scheduledFuture 为 null，则没有运行的任务
         * @return
         */
        public boolean isStop() {
            return scheduledFuture == null;
        }

        /**
         * 内存状态 scheduledFuture 不为 null，则存在运行的任务
         * @return
         */
        public boolean isRunning() {
            return scheduledFuture != null;
        }

        /**
         * 停止调度任务 <br />
         * 1. 内存状态设置为 null
         * 2. 调用 scheduledFuture#cancel 终止正在运行的调度任务
         */
        public void stop() {
            ScheduledFuture scheduledFuture = this.scheduledFuture;
            this.scheduledFuture = null;

            scheduledFuture.cancel(true);
        }
    }


    private class TaskRunner implements Runnable {
        private final Long taskId;
        public TaskRunner(TaskDefinitionV3 task) {
            this.taskId = task.getId();
        }

        @Override
        public void run() {
            TaskDefinitionV3 task = repository.findById(this.taskId).orElse(null);
            if (task != null && task.isEnable()) {
                TaskConfig taskConfig = TaskConfig.builder()
                        .name(task.getName())
                        .data(task.getData())
                        .build();
                taskService.runTask(taskConfig);
            }
        }
    }
}
